﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using ORM_Benchmark.Runner.EFv41;
using ORM_Benchmark.Runner.Interface;
using ORM_Benchmark.Runner.Linq2Sql;
using ORM_Benchmark.Runner.MassiveORM;

namespace ORM_Benchmark.Runner
{
    class Program
    {
        private const int _recordsToInsert = 1000;

        private static Stopwatch _stopWatch;
        static void Main(string[] args)
        {
            var connection = new Connect();

            _stopWatch = new Stopwatch();
            _stopWatch.Start();

            //LinqTests(connection);
            //MassiveTests(connection);
            //EFv41Tests(connection);
            //to run the other ef tests, comment out EfEntityTypeProduct's mapping in the context
            EFv41EntityMappingTests(connection);

            Console.ReadKey();
        }

        public static void OutputAndReset(string message)
        {
            _stopWatch.Stop();
            Console.WriteLine(message + " took " + _stopWatch.ElapsedMilliseconds + " ms");
            _stopWatch.Restart();
        }

        public static void LinqTests(IConnect connection)
        {
            var linqContext = new Linq2SqlProductContext(connection);
            OutputAndReset("newing up linq 2 sql");

            linqContext.Products.Where(x => !x.Discontinued).ToList();
            OutputAndReset("selecting with linq 2 sql");

            var linqProducts = new List<LinqProduct>();

            for (int i = 0; i < _recordsToInsert; i++)
                linqProducts.Add(new LinqProduct() { Category = "cat" + i, Name = "namer" + i, Discontinued = (i % 2 == 0) });
            OutputAndReset("prepare linq data insert");

            linqContext.Insert(linqProducts);
            OutputAndReset("linq inserts");

            linqProducts = linqContext.Products.Where(x => x.Discontinued).ToList();
            linqProducts.ForEach(prod => prod.Discontinued = false);
            OutputAndReset("prepare linq data update");

            linqContext.Update(linqProducts);
            OutputAndReset("linq updated " + linqProducts.Count + " records");
        }

        public static void EFv41Tests(IConnect connection)
        {
            var ef4ProdContext = new EFv41ProductContext(connection, false);
            OutputAndReset("newing up EF4");

            ef4ProdContext.Products.AsNoTracking().Where(x => !x.Discontinued).ToList();
            OutputAndReset("selecting with EF4");
            var ef4Products = new List<Efv41Product>();

            for (int i = 0; i < _recordsToInsert; i++)
                ef4Products.Add(new Efv41Product() { Category = "cat" + i, Name = "namer" + i, Discontinued = (i % 2 == 0) });
            OutputAndReset("prepare EF4 data insert");

            ef4ProdContext.Insert(ef4Products);
            OutputAndReset("EF4 inserts");

            ef4Products = ef4ProdContext.Products.Where(x => x.Discontinued).ToList();
            ef4Products.ForEach(prod => prod.Discontinued = false);
            OutputAndReset("prepare EF4 data update");

            ef4ProdContext.SaveChanges();
            OutputAndReset("EF4 updated " + ef4Products.Count + " records");

        }

        public static void EFv41EntityMappingTests(IConnect connection)
        {
            var ef4ProdContext = new EFv41ProductContext(connection, true);
            OutputAndReset("newing up EF4");

            ef4ProdContext.EntityProducts.AsNoTracking().Where(x => !x.Discontinued).ToList();
            OutputAndReset("selecting with EF4");
            var ef4Products = new List<EfEntityTypeProduct>();

            for (int i = 0; i < _recordsToInsert; i++)
                ef4Products.Add(new EfEntityTypeProduct() { Category = "cat" + i, Name = "namer" + i, Discontinued = (i % 2 == 0) });
            OutputAndReset("prepare EF4 data insert");

            ef4ProdContext.Insert(ef4Products);
            OutputAndReset("EF4 inserts");

            ef4Products = ef4ProdContext.EntityProducts.Where(x => x.Discontinued).ToList();
            ef4Products.ForEach(prod => prod.Discontinued = false);
            OutputAndReset("prepare EF4 data update");

            ef4ProdContext.SaveChanges();
            OutputAndReset("EF4 updated " + ef4Products.Count + " records");

        }

        public static void MassiveTests(IConnect connection)
        {
            var robContext = new MassiveProducts(connection);
            OutputAndReset("newing up Massive");

            robContext.All(where: "Discontinued = 0").ToList();
            OutputAndReset("selecting with Massive took");

            var massiveProducts = new List<dynamic>();

            for (int i = 0; i < _recordsToInsert; i++)
                massiveProducts.Add(new { Category = "cat" + i, Name = "namer" + i, Discontinued = (i % 2 == 0) });
            OutputAndReset("prepare Massive data insert");

            robContext.InsertAll(massiveProducts);
            OutputAndReset("Massive inserts");

            massiveProducts = robContext.All(where: "Discontinued = 1", columns: "Discontinued, Id").ToList();
            massiveProducts.ForEach(prod => prod.Discontinued = false);
            OutputAndReset("prepare Massive update");

            robContext.UpdateAll(massiveProducts);
            OutputAndReset("Massive updated " + massiveProducts.Count + " records");

        }
    }
}
